/* Copyright (C) 2010  Romolo Camplani, Marco Fortunato, Marco Marelli, Guido Rota, Fabio A. Schreiber et al.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package org.dei.perla.sys.persistence;

import java.sql.SQLException;
import java.util.ArrayList;

import org.dei.perla.component.Startable;
import org.dei.perla.sys.core.PerlaConfigurationException;
import org.dei.perla.sys.query.llqruntime.datastructures.Buffer;
import org.dei.perla.sys.query.llqruntime.datastructures.OutOfBoundsBufferException;
import org.dei.perla.utils.waiter.Waiter;

/**
 * La seguente � una sottoclasse della classe DataPersitent e si occuppa di realizzare
 * la persistenza dei dati perseguendo una sorta di politica basata sul numero di record,
 * sfruttando i metodi messi a disposizione della classe padre DataPersistent.
 * Pi� precisamente questo tipo di politica consite nel rendere persistenti i record presenti 
 * nel Buffer, ogni volta che sono presenti pi� di un certo numero di recod nel Buffer. 
 * La politica � realizzata mediante l'utilizzo di una inner class, che sostanzialemente crea 
 * un thread, che aziona il meccanismo di persistenza solo quando si accorge che nel buffer 
 * sono presenti il numero di record voluti. 
 * Il thread � volutamente nascosto a oloro che utilizzano la classe, ma che possono gestire 
 * agevolmente sfruttando i metodi messi a disposizione dall' interfaccia Startable, 
 * opportunamente implementati.
 * @author Luigi Rinaldi & Matteo Rovero
 *
 */
public class DataPersistentRecordPolitic extends DataPersistent { 

	private Waiter<Buffer> pWaiter;
	private Thread persistenceThread;
	private int numberOfRecords;
	private int actualNumberOfRecord;
	private boolean newTable = true; 
	/**
	 * Richiama il costruttore della superclasse
	 * @param buff oggetto Buffer da cui prelevare i record.
	 * @param nameOfTable  tabella MySql che conterr� i record del buff.
	 * @param numberOfRecords numero di record che devono essere presenti nel Buffer prima che possano 
	 * essere salvati in memoria. Per definizione non pu� essere negativo o nullo.
	 * @throws NotValidNameException eccezione sollevata nel caso in cui il nome della Tabella risulta 
	 * gi� utilizzato nel DB.
	 * @throws NullBufferException eccezione sollevata nel caso in cui il Buffer passato sia null.
	 * @throws OutOfBoundsException eccezione sollevata nel caso in cui il parametro numberOfRecords
	 * sia negativo o nullo.
	 * @throws PerlaConfigurationException 
	 */
	public DataPersistentRecordPolitic(Buffer buff, String nameOfTable, int numberOfRecords) throws NullBufferException, NotValidNameException, OutOfBoundsException, PerlaConfigurationException{
		super(buff, nameOfTable);
		if(numberOfRecords <= 0) throw new OutOfBoundsException();
		pWaiter = new Waiter<Buffer>();
		pWaiter.addWaitable(buff.getWaitable());
		this.numberOfRecords = numberOfRecords;
	}


	@Override
	public ArrayList<String[]> inspect() {
		// TODO Auto-generated method stub
		String head[] = {"Table name", "Actual number of records", "Max number of record", "Source buffer id"};
		String fields[] = {this.nameTable, new Integer(this.actualNumberOfRecord).toString(), new Integer(this.numberOfRecords).toString(), this.buff.toString()};
		ArrayList<String[]> list = new ArrayList<String[]>();
		list.add(head);
		list.add(fields);
		return null;
	}


	@Override
	protected void loop() throws Exception {
		while(!persistenceThread.isInterrupted()){
			actualNumberOfRecord =  buff.getBuffer().size();
			if(buff.getWaitable() == pWaiter.waitNext() && actualNumberOfRecord >= numberOfRecords){	
				if(newTable){
					try {
						System.out.println("creo tabella");
						createTable();
						newTable=false;
					} catch (SQLException e1) {
						e1.printStackTrace();
					} catch (ClassNotFoundException e2) {
						e2.printStackTrace();
					}
				}
				try {
					saveRecords(numberOfRecords);
				} catch (OutOfBoundsBufferException e3) {
					e3.printStackTrace();
				}
			}
		}
	}


	@Override
	public void respawn() {
		// TODO Auto-generated method stub
		
	}	

}
